#include "../includes/TaskConsumer.h"
#include <cstring>
#include <iostream>
#include <chrono>

// 静态成员定义
TaskConsumer* TaskConsumer::instance_ = nullptr;

TaskConsumer& TaskConsumer::getInstance() {
    // C++11 标准保证静态局部变量的初始化是线程安全的 (Meyer's Singleton)
    static TaskConsumer instance; // 默认创建4个线程
    return instance;
}

// 构造函数：初始化线程池
TaskConsumer::TaskConsumer(int num_threads) 
    : stop_(false), idle_threads_(num_threads), total_threads_(num_threads) {

    for (int i = 0; i < num_threads; ++i) {
        workers_.emplace_back(&TaskConsumer::worker_loop, this);
    }
    std::cout << "TaskConsumer initialized with " << num_threads << " threads." << std::endl;
}

TaskConsumer::~TaskConsumer() {
    {
        std::unique_lock<std::mutex> lock(queue_mutex_);
        stop_ = true;
    }
    condition_.notify_all(); // 通知所有等待的线程

    for (std::thread &worker : workers_) {
        if (worker.joinable()) { // 检查线程是否可以被 join
            worker.join();
        }
    }
    std::cout << "TaskConsumer destroyed. All threads stopped." << std::endl;
}

bool TaskConsumer::add_task() {
    {
        TaskManager& task_manager = TaskManager::getInstance();
        std::unique_lock<std::mutex> lock(queue_mutex_);
        if (stop_) {
            // 如果线程池已停止，不再接受新任务
            return false;
        }
        std::string task_str;
        if(!task_manager.task_empty()){
            task_manager.get_task(task_str); // 从任务队列获取任务
            // 将任务包装成 std::function<void()> 并加入队列
            tasks_.emplace([task_str] {
                TaskConsumer::run(task_str);
            });
            condition_.notify_one(); // 通知一个等待的线程来执行任务
        }
    }

    return true; // 任务成功添加到队列
}

int TaskConsumer::idle_threads() const {
    // 返回当前空闲线程数量
    // 注意：这个值是瞬时的，在多线程环境下可能很快变化
    return idle_threads_.load();
}

void TaskConsumer::worker_loop() {
    while (true) {
        std::function<void()> task;

        {
            std::unique_lock<std::mutex> lock(queue_mutex_);

            // 等待直到有任务或线程池停止
            condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); });

            // 检查是否需要退出
            if (stop_ && tasks_.empty()) {
                return; // 退出循环，线程结束
            }

            // 如果有任务，则取出一个
            if (!tasks_.empty()) {
                task = std::move(tasks_.front());
                tasks_.pop();
            }
        }

        if (task) {
            // 在执行任务前，将线程标记为忙碌
            idle_threads_.fetch_sub(1);
            // 执行任务
            task();
            // 任务执行完毕后，将线程标记为空闲
            idle_threads_.fetch_add(1);
        }
        // 如果 task 为空（例如，被虚假唤醒但队列仍为空），则循环继续
    }
}

void TaskConsumer::run(const std::string& task_str) {
    // 这里解析 task_str，决定调用哪个具体函数
    TaskManager& task_manager = TaskManager::getInstance();
    
    int task_type = task_manager.task_type(task_str);
    std::string resp_str;

    if (task_type == 0) {
        TaskManager::WriteTask task; // 填充 task
        TaskManager::WriteResponse resp;
        TaskManager::WriteTask::from_string(task_str, task);// 将字符串解析为具体结构体
        write(task, resp);
        TaskManager::WriteResponse::to_string(resp, resp_str);// 将响应结构体解析回字符串
        task_manager.add_resp(resp_str); // 将执行结果放入响应队列
    } 
    else if (task_type == 1) {
        TaskManager::CatTask task; // 填充 task
        TaskManager::CatResponse resp;
        TaskManager::CatTask::from_string(task_str, task); // 将字符串解析为具体结构体
        cat(task, resp);
        TaskManager::CatResponse::to_string(resp, resp_str); // 将响应结构体解析回字符串
        task_manager.add_resp(resp_str); // 将执行结果放入响应队列
    }
    else if(task_type == 2){
        TaskManager::TouchTask task; // 填充 task
        TaskManager::TouchResponse resp;
        TaskManager::TouchTask::from_string(task_str, task); // 将字符串解析为具体结构体
        touch(task, resp);
        TaskManager::TouchResponse::to_string(resp, resp_str); // 将响应结构体解析回字符串
        task_manager.add_resp(resp_str); // 将执行结果放入响应队列
    }
    else if(task_type == 3){
        TaskManager::RmTask task; // 填充 task
        TaskManager::RmResponse resp;
        TaskManager::RmTask::from_string(task_str, task); // 将字符串解析为具体结构体
        rm(task, resp);
        TaskManager::RmResponse::to_string(resp, resp_str); // 将响应结构体解析回字符串
        task_manager.add_resp(resp_str); // 将执行结果放入响应队列
    }
    else if(task_type == 4){
        TaskManager::LsTask task; // 填充 task
        TaskManager::LsResponse resp;
        TaskManager::LsTask::from_string(task_str, task); // 将字符串解析为具体结构体
        ls(task, resp);
        TaskManager::LsResponse::to_string(resp, resp_str); // 将响应结构体解析回字符串
        task_manager.add_resp(resp_str); // 将执行结果放入响应队列
    }
}

// 实现具体任务函数
void TaskConsumer::write(const TaskManager::WriteTask& task, TaskManager::WriteResponse& resp) {
    FileApi& file_api = FileApi::getInstance();
    int fd = file_api.open(task.file_name);
    if(fd == -1)return;
    resp.task_id = task.task_id;
    resp.type = task.type;
    file_api.lseek(fd, 0, FILE_END); // 将读写偏移量置为末尾
    int write_size = file_api.write(fd, task.buf, task.write_size); // 在末尾追加写入数据
    if(write_size == -1)resp.status_code = 0; // 失败用0
    else resp.status_code = 1; // 成功用1
    resp.bytes_written = write_size;
    
}

void TaskConsumer::cat(const TaskManager::CatTask& task, TaskManager::CatResponse& resp) {
    FileApi& file_api = FileApi::getInstance();
    int fd = file_api.open(task.file_name);
    if(fd == -1)return;
    char buf[256 * 1024];
    file_api.lseek(fd, 0, FILE_START); // 将读写偏移量置为开头
    int read_size = file_api.read(fd, buf, 256 *  1024);

    resp.task_id = task.task_id;
    resp.type = task.type;
    resp.content_length = read_size;
    if(resp.content != nullptr){
        delete [] resp.content;
    }
    if(read_size == -1){
        resp.status_code = 0;
        return; // 异常情况不拷贝
    }
    resp.status_code = 1;
    resp.content = new char[read_size];
    std::memcpy(resp.content, buf, read_size); // 将文件内容拷贝到响应体
}

void TaskConsumer::touch(const TaskManager::TouchTask& task, TaskManager::TouchResponse& resp) {
    FileApi& file_api = FileApi::getInstance();
    int fd = file_api.open(task.file_name);
    resp.task_id = task.task_id;
    resp.type = task.type;
    if(fd == -1){
        resp.status_code = 0;
        return;
    }
    resp.status_code = 1;
}

void TaskConsumer::rm(const TaskManager::RmTask& task, TaskManager::RmResponse& resp) {
    FileApi& file_api = FileApi::getInstance();
    int fd = file_api.open(task.file_name);
    resp.task_id = task.task_id;
    resp.type = task.type;
    if(fd == -1){
        resp.status_code = 0;
        return;
    }
    if(file_api.del(fd) < 0){// 根据句柄删除文件
        resp.status_code = 0;
        return;
    }
    resp.status_code = 1;
}

// ls比较特殊, 涉及到更底层的系统调用, 需要访问磁盘的超级块部分
void TaskConsumer::ls(const TaskManager::LsTask& task, TaskManager::LsResponse& resp) {
    std::string disk_file_path = "/home/ubuntu/FileSysSimulate/file-sys-simulate/disk_file"; // 用于模拟磁盘的文件路径
    DiskManager& disk_manager = DiskManager::getInstance(disk_file_path); // 先初始化1个磁盘管理器
    DiskManager::SuperBlock super_block;
    disk_manager.super_block_load(super_block);
    std::vector<std::string> files;
    for(int i = 0; i < INODE_NUM; i++){
        if(super_block.inode_state[i]){
            DiskManager::Inode inode;
            disk_manager.inode_get(i, inode);
            files.push_back(inode.path);
        }
    }

    // --- 将 files 中的路径拷贝到 resp.file_entries ---
    // 首先清空 resp 中可能已有的内容（虽然在函数入口时通常是空的）
    resp.clear(); // 使用 LsResponse 的辅助方法

    int file_count = 0;
    for (const auto& file_path : files) {
        if (file_count >= TaskManager::LsResponse::MAX_FILES) {// 检查文件数量超过最大限制
            break;
        }

        // 检查文件名长度是否超过限制 (128 字节)
        if (file_path.length() > 128) {
            // 如果文件名过长，选择跳过
            continue;
        }

        // 为当前文件名分配内存
        size_t name_len = file_path.length();
        char* new_name = new char[name_len + 1]; // +1 for null terminator

        // 将 std::string 的内容拷贝到新分配的内存中
        std::strncpy(new_name, file_path.c_str(), name_len);
        new_name[name_len] = '\0'; // 确保以 '\0' 结尾

        // 将指针存入 resp 的指针数组中
        resp.file_entries[file_count] = new_name;

        file_count++;
    }

    // 更新 resp 中的文件计数
    resp.type = task.type;
    resp.task_id = task.task_id;
    resp.file_count = file_count;
    resp.status_code = 1;
}